'''
Created on 18/09/2011

@author: Ike-kun <ragnell22@gmail.com>
'''

from ConfigViewer import ConfigViewer
from LogGenerator import RandomGenerator
from Reader import Reader
from Filter import Filter
from Tkinter import LabelFrame
import Tix as tix
import tkFileDialog
import tkMessageBox
import time
import sys
import math

class LogViewer(object):
    def __init__(self,logsGenerated,maxLogDisplay):
        self.logsGenerated = logsGenerated
        self.maxLogDisplay = maxLogDisplay
        self.root = tix.Tk()
        self.root.geometry("%dx%d+%d+%d" % (800,503,200,150))
        self.root.protocol("WM_DELETE_WINDOW",self.destroy)
        self.root.title("Log4Python Log Viewer")
        self.root.configure(bg="gray")
        self.root.resizable(0,0)
        self.textfields = []
        self.tableRows = []
        self.dataReaded = []
        self.pages = []
        self.fileLoaded = False
        self.havePages = False
        self.radioVar = tix.IntVar()
        self.comboSelection = ""
        self.drawWindow()
        self.root.mainloop()

    def drawWindow(self):
        self.createComboBox()
        self.createTextFields()
        self.createButtons()
        self.createHeaders()
        self.createTextArea()
        self.createMenu()

    def createComboBox(self):
        self.lf = LabelFrame(self.root,text="Controls",bg="gray")
        tix.Label(self.lf,text="Filter Priority:",relief=tix.RIDGE,width=20,bg="gray").grid(row=0,column=0)
        self.combo = tix.ComboBox(self.lf)
        levelList = ['','ERROR','WARN','INFO','DEBUG','FATAL']
        for item in levelList:
            self.combo.slistbox.listbox.insert('end',item)
        self.combo.slistbox.listbox.bind('<ButtonRelease-1>',self.selected)
        self.combo.slistbox.listbox.configure(height=len(levelList),bg='white')
        self.combo.grid(row=0,column=1,sticky=tix.W)
        self.lf.place(in_=self.root)

    def createTextFields(self):
        labelList = ["Filter Time:","Filter Category:","Filter NDC:","Filter Message:"]
        for i in range(len(labelList)):
            tix.Label(self.lf,text=labelList[i],relief=tix.RIDGE,width=20,bg="gray").grid(row=i+1,column=0)
            temp = tix.Entry(self.lf,relief=tix.SUNKEN,width=92)
            temp.grid(row=i+1,column=1)
            self.textfields.append(temp)

    def createButtons(self):
        bArea = tix.Frame(bg="gray")
        a = ["Exit","Clear","Filter"]
        color = 'gray'
        tix.Button(bArea,text=a[0],width=9,bg=color,command=self.destroy).grid(row=0,column=0,pady=3)
        tix.Button(bArea,text=a[1],width=9,bg=color,command=self.clear).grid(row=1,column=0,pady=3)
        tix.Button(bArea,text=a[2],width=9,bg=color,command=self.filtering).grid(row=2,column=0,pady=3)
        bArea.place(in_=self.root,x=710,y=10)

    def createHeaders(self):
        headerArea = tix.Frame(bg="gray")
        tix.Label(headerArea,text=" # ",bg="gray",relief=tix.RAISED,width=3).grid(row=0,column=0)
        tix.Label(headerArea,text="Time",bg="gray",relief=tix.RAISED,width=15).grid(row=0,column=1)
        tix.Label(headerArea,text="Priority",bg="gray",relief=tix.RAISED,width=8).grid(row=0,column=2)
        tix.Label(headerArea,text="Category",bg="gray",relief=tix.RAISED,width=29).grid(row=0,column=4)
        tix.Label(headerArea,text="NDC",bg="gray",relief=tix.RAISED,width=15).grid(row=0,column=5)
        tix.Label(headerArea,text="Message",bg="gray",relief=tix.RAISED,width=34).grid(row=0,column=6)
        headerArea.place(in_=self.root,x=5,y=135,width=780)

    def createPages(self,data,pageNumber):
        pages = []
        for i in range(pageNumber):
            page = []
            for j in range(len(data)):
                page.append(data.pop(0))
                if(j == 1499):
                    break
            pages.append(page)
        return pages

    def createTable(self,data):
        if(not self.havePages):
            totalRange = len(data) / 5
            paginate = False
            if(totalRange > 300):
                pageNumber = int(math.ceil(totalRange / 300.0))
                if(pageNumber > 31):
                    pageNumber = 31
                self.pages = self.createPages(data,pageNumber)
                totalRange = len(self.pages[self.radioVar.get()]) / 5
                data = list(self.pages[self.radioVar.get()])
                paginate = True
        else:
            totalRange = len(self.pages[self.radioVar.get()]) / 5
            pageNumber = int(math.ceil(totalRange / 300.0))
            data = list(self.pages[self.radioVar.get()])
            paginate = False
        self.root.update_idletasks()
        self.eventArea = tix.Frame(bg="gray")
        self.canvas = tix.Canvas(self.eventArea,borderwidth=0,scrollregion=(0,0,0,totalRange*34),width=780)
        self.tableArea = tix.Frame(self.canvas)
        sizes = [3,15,9,29,15,35]
        font = ["Helvetica",9]
        color = 'white'
        for i in range(totalRange):
            cols = []
            for j in range(6):
                if(j == 0):
                    e = tix.Text(self.tableArea,bg=color,relief=tix.RIDGE,width=3,height=2,font=(font))
                    e.insert(tix.INSERT,str(i))
                    e.bind('<ButtonRelease-1>',self.showInfo)
                else:
                    e = tix.Text(self.tableArea,bg=color,relief=tix.RIDGE)
                    e.configure(width=sizes[j],height=2,font=(font))
                    e.insert(tix.INSERT,data.pop(0))
                e.grid(row=i,column=j)
                cols.append(e)
            self.tableRows.append(cols)
        self.root.update_idletasks()
        scrollbar = tix.Scrollbar(self.eventArea,orient="vertical",command=self.canvas.yview)
        self.canvas.configure(yscrollcommand=scrollbar.set)
        scrollbar.pack(side="right",fill="y")
        self.canvas.pack(side="left",fill="both",expand=False)
        self.canvas.create_window((0,0),window=self.tableArea,anchor="nw")
        if(paginate):
            self.pageArea = tix.Frame(bg="gray")
            for x in range(pageNumber):
                e = tix.Radiobutton(self.pageArea,text=str(x),indicatoron=0,font=["Times",6])
                e.configure(value=x,variable=self.radioVar,command=self.radio)
                e.grid(row=0,column=x)
            self.pageArea.place(in_=self.root,x=250,y=317)
        self.eventArea.place(in_=self.root,x=5,y=155,width=780,height=160)
        self.root.update_idletasks()

    def createTextArea(self):
        textArea = LabelFrame(self.root,text="Details",bg="gray")
        self.detailsText = tix.Text(textArea)
        self.detailsText.insert(0.0,"")
        self.detailsText.pack(expand=0,fill='both')
        textArea.place(in_=self.root,x=5,y=330,width=780,height=170)

    def createMenu(self):
        self.root.option_add('*tearOff',tix.FALSE)
        menu = tix.Menu(self.root)
        self.root.configure(menu=menu)
        filemenu = tix.Menu(menu)
        testmenu = tix.Menu(menu)
        menu.add_cascade(label="File",menu=filemenu)
        filemenu.add_command(label="Reload File",command=self.reload)
        filemenu.add_command(label="Open File...",command=self.loadFile)
        filemenu.add_command(label="Exit",command=self.destroy)
        menu.add_cascade(label="Testing",menu=testmenu)
        testmenu.add_command(label="Generate New Logs",command=self.runDummy)
        testmenu.add_command(label="Configure",command=self.configure)

    def loadFile(self):
        self.fileName = tkFileDialog.askopenfilename(filetypes=[('','*.csv'),('','*.xml')])
        if(self.fileName.endswith('.csv') or self.fileName.endswith('.xml')):
            self.root.title("Log4Python Log Viewer - " + self.fileName)
            self.havePages = False
            self.radioVar.set(0)
            self.readData()
        else:
            tkMessageBox.showerror("Error","Cannot open this file\n")

    def readData(self):
        if(self.fileLoaded):
            self.tableArea.destroy()
            self.canvas.destroy()
            self.eventArea.destroy()
            self.havePages = False
            self.radioVar.set(0)
            self.pageArea.destroy()
        if(self.fileName.endswith('.xml')):
            self.dataReaded = Reader(self).readXML(self.fileName,self.maxLogDisplay)
        else:
            self.dataReaded = Reader(self).readCSV(self.fileName,self.maxLogDisplay)
        self.fileLoaded = True
        self.updateGUI()

    def updateGUI(self):
        self.tableRows = []
        data = list(self.dataReaded)
        self.createTable(data)
        self.combo.configure(value='')
        self.comboSelection = ''
        self.clearTextArea()
        self.clear()

    def selected(self,event):
        selectedValue = self.combo.slistbox.listbox.curselection()[0]
        self.comboSelection = self.combo.slistbox.listbox.get(selectedValue)

    def reload(self):
        if(self.fileLoaded):
            self.tableArea.destroy()
            self.canvas.destroy()
            self.eventArea.destroy()
            self.updateGUI()
        else:
            self.showError("There is no file to reload\n")

    def filtering(self):
        filters = []
        validEntry = False
        for i in self.textfields:
            if(i.get() != ''):
                validEntry = True
                filters.append(i.get())
            else:
                filters.append("No Filter")
        if(self.comboSelection != '' and self.comboSelection != "No Filter"):
            validEntry = True
        else:
            self.comboSelection = "No Filter"
        if(validEntry and self.fileLoaded):
            self.clearTextArea()
            newData = Filter(self.dataReaded).doFilter(filters,self.comboSelection)
            self.tableRows = []
            self.havePages = False
            self.radioVar.set(0)
            self.pageArea.destroy()
            self.createTable(newData)
        else:
            self.showError("Nothing to filter\n")
            self.reload()

    def showError(self,msg):
        self.combo.configure(value='')
        tkMessageBox.showerror("Error",msg)

    def configure(self):
        ConfigViewer(self.root)

    def radio(self):
        self.havePages = True
        self.reload()

    def runDummy(self):
        RandomGenerator(self.logsGenerated)
        tkMessageBox.showinfo("Done","New Logs Generated\n")

    def clear(self):
        for i in self.textfields:
            i.delete(0,tix.END)

    def showInfo(self,event):
        self.clearTextArea()
        data = ""
        for i in range(len(self.tableRows)):
            if(i == int(event.widget.get("1.0",tix.END))):
                data += "Time: " + self.tableRows[i][1].get("1.0",tix.END)
                data += "Priority: " + self.tableRows[i][2].get("1.0",tix.END)
                data += "Category: " + self.tableRows[i][3].get("1.0",tix.END)
                data += "NDC: " + self.tableRows[i][4].get("1.0",tix.END)
                data += "Message: " + self.tableRows[i][5].get("1.0",tix.END)
        self.detailsText.insert(0.0,data)

    def clearTextArea(self):
        self.detailsText.delete(0.0,tix.END)
        
    def editTextArea(self, message):
        self.clearTextArea()
        self.detailsText.insert(0.0, message)
        self.root.update_idletasks()

    def destroy(self):
        self.root.destroy()
        sys.exit(0)
